package edu.uvic.TabViz.framework;

import java.io.Serializable;
import java.util.ArrayList;

import android.graphics.Color;
import edu.uvic.TabViz.framework.primitives.Camera;
import edu.uvic.TabViz.framework.primitives.Object3D;
import edu.uvic.TabViz.framework.primitives.Object3DSerialized;

public class World implements Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = -4450115365358524123L;
	protected float mEyeZ = -24.0f;
	protected float[] background = new float[]{0,0,0,0};
	protected ArrayList<Object3D> objects;
	protected int objectsCount;
	protected Camera camera;


	public World(){
		objects = new ArrayList<Object3D>();
		camera = new Camera();
		camera.getPosition().setZ(mEyeZ);
	}
	
	public World(WorldReplicate ws){
		camera = new Camera(ws.camera);
		setBackground(ws.background);
 		objects = new ArrayList<Object3D>();
		for (Object3DSerialized o : ws.getObjects())
			objects.add(new Object3D(o));
		objectsCount = objects.size();
		mEyeZ = ws.mEyeZ;
		camera.getPosition().setZ(ws.mEyeZ);
	}
	
	public World(World world) {
		objects = new ArrayList<Object3D>();
		this.mEyeZ = world.mEyeZ;
		setBackground(world.background);
		camera = new Camera(world.camera);
		camera.getPosition().setZ(mEyeZ);
		for (int i=0 ; i< world.objectsCount; i++)
			this.addObject(world.getObjects().get(i));
	}

	public float[] getBackground() {
		return background;
	}

	public void setBackground(float[] background) {
		this.background = background;
	}

	public void clearObjects() {
		if(getObjectsCount() > 0) {
			objects.clear();
			objectsCount = 0;
		}
	}

	public void setCamera(Camera camera) {
		this.camera = camera;
	}

	public Camera getCamera() {
		return this.camera;
	}

	public float getmEyeZ() {
		return mEyeZ;
	}

	public void setmEyeZ(float eyeZ) {
		camera.getPosition().setZ(eyeZ);
		this.mEyeZ = eyeZ;
	}

	public ArrayList<Object3D> getObjects() {
		return objects;
	}

	public void setObjects(ArrayList<Object3D> objects) {
		this.objects = objects;
	}

	public int getObjectsCount() {
		return objectsCount;
	}

	public void setObjectsCount(int objectsCount) {
		this.objectsCount = objectsCount;
	}

	public void addObject(Object3D child) {
		objects.add(child);
		objectsCount = objects.size();
	}

	public boolean removeObject(Object3D child) {
		boolean result = objects.remove(child);
		objectsCount = objects.size();
		return result;
	}

	protected boolean hasObject(Object3D child) {
		for(int i=0; i<objectsCount; ++i) {
			if(objects.get(i).equals(child)) return true;
		}
		return false;
	}

	public void setBackground(float r, float g, float b, float a) {
		background[0] = r;
		background[1] = g;
		background[2] = b;
		background[3] = a;
	}

	public void setBackground(int color) {
		setBackground(Color.red(color), Color.green(color), Color.blue(color), Color.alpha(color));
	}

	public WorldReplicate replicate(){
		WorldReplicate ws = new WorldReplicate();
		ws.setCamera(this.camera);
		ws.setBackground(this.background);
		ws.objectsCount = this.objectsCount;
		ws.objects = new ArrayList<Object3DSerialized>();
		ws.mEyeZ  = this.mEyeZ;
		for(Object3D o : objects)
			ws.objects.add(o.serialize());
		ws.camera.getPosition().setZ(mEyeZ);
		return ws;
	}
	public boolean set(WorldReplicate ws){
		camera = new Camera(ws.camera);
		setBackground(ws.background);
		this.objectsCount = ws.objectsCount;
		objects = new ArrayList<Object3D>();
		for (Object3DSerialized o : ws.getObjects())
			objects.add(new Object3D(o));
		objectsCount = objects.size();
		mEyeZ = ws.mEyeZ;
		camera.getPosition().setZ(ws.mEyeZ);
		return true;
	}
	
	@Override
	public int hashCode() {
		int hash = 0;
		for (Object3D o : getObjects())
			hash += o.hashCode();
		return hash + background.hashCode() + camera.hashCode();


	}
}
